package com.hh.service.impl;

import com.hh.mapper.PostBarMapper;
import com.hh.mapper.UserBarRelevancyMapper;
import com.hh.pojo.Category;
import com.hh.pojo.MessageModel;
import com.hh.pojo.PostBar;
import com.hh.pojo.User;
import com.hh.service.PostBarService;
import com.hh.service.PostService;
import com.hh.utils.FileTool;
import com.hh.utils.ServiceTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

@Service
//@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
public class PostBarServiceImpl implements PostBarService {

    @Autowired
    private PostBarMapper postBarMapper;

    @Autowired
    private UserBarRelevancyMapper userBarRelevancyMapper;

    @Override
    public Map<String, Object> getPostBarList() {
        return getPostBarListByMap(new HashMap<>());
    }

    @Override
    public Map<String, Object> getPostBarListByMap(Map<String, Object> map) {
        try {
            return ServiceTool.getList(postBarMapper.getPostBarListByMap(map));
        }catch (Exception e){  /*数据库查询发生异常*/
            e.printStackTrace();
            return ServiceTool.getListWrong();
        }
    }

    @Override
    public Map<String, Object> getDetailedBarInfoById(int barId, String uname) {
        HashMap<String, Object> rs = new HashMap<>();
        MessageModel rsModel = new MessageModel(200, "信息获取成功！");
        boolean joined = false;
        PostBar bar = null;


        try {
            // 获取贴吧信息
            bar = postBarMapper.getDetailedBarById(barId);

            // 获取当前登录用户 加入贴吧的情况
            // 如果用户名 为 null （用户未登录）  默认用户未加入
            if (uname != null) {
                Map<String, Object> map = new HashMap<>();

                map.put("uname", uname);
                map.put("barId", barId);

                joined = userBarRelevancyMapper.getRvcByMap(map) != null;
            }
        }catch (Exception e){
            e.printStackTrace();
            rsModel.setResult_code(303);
            rsModel.setMsg("数据库查询发生异常！");
        }

        // 返回结果
        rs.put("rs", rsModel);
        rs.put("barInfo", bar);
        rs.put("joined", joined);

        return rs;
    }

    /**
     * 根据贴吧id  检测 这个贴吧是否是 特殊（私密）贴吧
     * @param barId 要检测的贴吧id
     * @return true 表示 是特殊贴吧， 反之
     */
    private boolean checkSpecialBar(int barId){
        return postBarMapper.checkBarSpecial(barId) > 0;
    }

    /**
     *  当前登录用户（uname对应）退出 一个贴吧
     * @param uname  用户名
     * @param barId  贴吧id
     * @return 退出结果
     */
    @Override
    public MessageModel userExitBar(String uname, int barId) {
        MessageModel messageModel = new MessageModel(200, "退出贴吧成功！");
        Map<String, Object> map;

        if (checkSpecialBar(barId)){ // 如果是特殊贴吧则 不可退出
            messageModel.setResult_code(714);
            messageModel.setMsg("特殊贴吧暂时不支持退出~！");
        }else {
            map = new HashMap<>();
            map.put("uname", uname);
            map.put("barId", barId);
            try {
                if (userBarRelevancyMapper.deleteRvc(map) < 1){ //增加记录受影响行数不为1
                    messageModel.setResult_code(301);
                    messageModel.setMsg("退出失败：数据库删除失败。");
                }
            }catch (Exception e){
                messageModel.setResult_code(303);
                messageModel.setMsg("退出失败：数据库删除发生异常!");
                e.printStackTrace();
            }
        }

        return messageModel;
    }

    /**
     *  当前登录用户（uname对应）加入 一个贴吧
     * @param uname  用户名
     * @param barId  贴吧id
     * @return 加入结果
     */
    @Override
    public MessageModel userJoinBar(String uname, int barId) {
        MessageModel messageModel = new MessageModel(200, "加入贴吧成功！");
        Map<String, Object> map = new HashMap<>();

        map.put("uname", uname);
        map.put("barId", barId);
        try {
            if (userBarRelevancyMapper.addRvc(map) < 1){ //增加记录受影响行数不为1
                messageModel.setResult_code(300);
                messageModel.setMsg("加入失败：数据库插入失败。");
            }
        }catch (Exception e){
            messageModel.setResult_code(303);
            messageModel.setMsg("加入失败：数据库插入发生异常!");
            e.printStackTrace();
        }

        return messageModel;
    }

    /**
     * 设置推荐贴吧 （将参数数组内的贴吧设置为推荐 -- 1  其他设置为 不推荐 -- 0）
     * 由于涉及到多项数据库操作   所以要为此方法配置事务
     * @param barIds 要设置为 推荐的 贴吧id 数组
     * @return messageModel 设置结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public MessageModel setRecommendBars(int[] barIds) {
        MessageModel rs = new MessageModel();
        rs.setResult_code(200);  /*默认成功*/
        rs.setMsg("推荐贴吧设置成功！");

        try {
            // 将原来的所有贴吧设置为 不推荐
            postBarMapper.resetAllBarRec();

            // 将参数数组内的贴吧都设置为 推荐
            if (barIds != null && barIds.length > 0){
                postBarMapper.setBarsRec(barIds);
            }
        }
        catch (Exception e){
            rs.setResult_code(303);
            rs.setMsg("数据库更新（贴吧 - 推荐）发生异常。");
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  //由于手动catch了异常， 此处需要手动进行事务回滚
        }
        return rs;
    }

    @Override
    public MessageModel checkUserBarRelevance(String uname, int barId) {
        Map<String, Object> map = new HashMap<>();

        map.put("uname", uname);
        map.put("barId", barId);

//        if (userBarRelevancyMapper.getRvcByIdName(barId, uname) == null){ //在数据库中未查询到对应的用户-贴吧加入关系
        if (userBarRelevancyMapper.getRvcByMap(map) == null){ //在数据库中未查询到对应的用户-贴吧加入关系
            return new MessageModel(602, "目前登录用户暂未加入该贴吧。");
        }else { //查询到了对应的加入关系
            return new MessageModel(601, "目前登录用户已加入该贴吧。");
        }
    }

    @Override
    public Map<Integer, Boolean> getUserBarRvc(String uname, List<PostBar> barList) {
        Map<Integer, Boolean> map = new HashMap<>();

        for (PostBar postBar : barList) {
            if ("".equals(uname)){  //用户名为空字符串表示 当前未登录
                map.put(postBar.getId(), false); //false表示未加入  true表示已加入  未登录默认显示为false
                continue;
            }
            if (checkUserBarRelevance(uname, postBar.getId()).getResult_code() == 602) //602表示未加入
                map.put(postBar.getId(), false);
            else  //602表示未加入
                map.put(postBar.getId(), true);
        }

        return map;
    }

    /**
     * 增加一个贴吧（文件+数据库）  由于涉及到多项数据库操作   所以要为此方法配置事务
     * @param name 贴吧名
     * @param checkedCategories 贴吧对应分类的id   int类型
     * @param headImg 贴吧头像文件
     * @param describe 贴吧描述
     * @param path 贴吧头像文件存储的文件夹地址
     * @return 添加结果
     */
    @Override
//    @Transactional(rollbackFor = {Exception.class})
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
public MessageModel addPostBar(String name, int[] checkedCategories, MultipartFile headImg, String describe, String path) {
    /*path 表示文件(贴吧头像)上传保存的路径  由controller request.getServletContext().getRealPath() 获得  到barAvatar目录*/
    PostBar barToInsert = new PostBar();
    MessageModel rs = new MessageModel();
    File filePath = new File(path);  //文件上传路径（不包括文件名）
    String saveName;  /*文件保存名*/
    String separator = File.separator; //定义分隔符
    int i;  /*文件名 小数点位置*/
    int newId = postBarMapper.getNextVal(); //新贴吧的id编号
    String fileType;  /*文件类型 包括.*/
    LinkedList<Category> categoryLinkedList = new LinkedList<>();

    barToInsert.setName(name);
    barToInsert.setDescribe(describe);
    barToInsert.setBarImg(headImg.getOriginalFilename()); /*如果上传了头像文件，先以源文件命名，如果没有，那此处会是空字符串“”*/
    for (int category : checkedCategories) {  // 此处仅有类别id 来初始化类别 然后赋值给要添加的 postBar
        categoryLinkedList.add(new Category(category));
    }
    barToInsert.setCategoryList(categoryLinkedList);
    rs.setResult_code(200);  /*默认成功*/
    rs.setMsg("贴吧添加成功！");

    try {
        // 如果上传了文件的话， 将贴吧头像以新贴吧编号命名（id） 保存     将文件保存到服务器
        if (headImg.getSize() != 0){
            i = Objects.requireNonNull(headImg.getOriginalFilename()).lastIndexOf('.');
            fileType = headImg.getOriginalFilename().substring(i);  /*包括.*/
            fileType = fileType.toLowerCase(); //一律转小写
            saveName = newId + fileType;

            barToInsert.setBarImg(saveName);
            headImg.transferTo(new File(filePath + separator + saveName));
        }
        //将贴吧记录写入数据库
        if (postBarMapper.addPostBar(barToInsert) < 1){
            rs.setResult_code(300);
            rs.setMsg("数据库（贴吧）插入失败！");
        }
        //将贴吧分类关联记录写入数据库
        for (int category : checkedCategories) {
            HashMap<String, Integer> map = new HashMap<>();
            map.put("barId", newId);
            map.put("categoryId", category);
            try {
                if (postBarMapper.addBarCategoryRelevancy(map) < 1){
                    rs.setResult_code(300);
                    rs.setMsg("数据库（贴吧关联分类）插入失败！");
                }
            }catch (Exception e){
                rs.setResult_code(303);
                rs.setMsg("数据库插入(贴吧关联分类)发生异常。");
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  //由于手动catch了异常， 此处需要手动进行事务回滚
            }
        }
    }catch (IOException e){
        rs.setResult_code(408);
        rs.setMsg("文件写入发生异常。");
        e.printStackTrace();
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  //由于手动catch了异常， 此处需要手动进行事务回滚
    }
    catch (Exception e){
        rs.setResult_code(303);
        rs.setMsg("数据库插入（贴吧）发生异常。");
        e.printStackTrace();
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  //由于手动catch了异常， 此处需要手动进行事务回滚
    }
    return rs;
}

    /**
     *
     * @param id 要删除记录的 id
     * @param path 贴吧头像路径（不包括图片名）
     * @return  删除结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public MessageModel deletePostBarById(int id, String path) {
        MessageModel messageModel = new MessageModel(200, "贴吧删除成功！");
        PostBar bar = postBarMapper.getSimpleBarById(id);
        String barImg = bar.getBarImg();

        try {
            if (postBarMapper.delPostBarById(id) < 1){ //删除记录受影响行数不为1
                messageModel.setResult_code(301);
                messageModel.setMsg("数据库删除失败。");
            }else {  //数据库记录删除正常  即受影响行数 = 1   再删除文件（贴吧头像）
                if (!"bar_default_img.jpg".equals(barImg)){  //如果是默认头像 不删除头像文件
                    if (FileTool.deleteFile(path + barImg) == 0){
                        messageModel.setResult_code(409);
                        messageModel.setMsg("贴吧头像文件删除失败。");
                    }
                }
            }
        }catch (Exception e){
            messageModel.setResult_code(303);
            messageModel.setMsg("数据库删除发生异常!");
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  //由于手动catch了异常， 此处需要手动进行事务回滚
        }

        return messageModel;
    }
}
